//
//  FOutlineView.m
//  SolarSeek
//
//  Created by Erick Fejta on 05/03/22.
//  Copyright 2005 Erick Fejta. All rights reserved.
//

#import "FOutlineViewDataSource.h"
#import "FSelectorWrapper.h"

@implementation FOutlineViewElement
- (BOOL)expandable { return [[self children] count] > 0; }
- (NSArray *)children { return [NSArray array]; }
- (id<FOutlineViewElement>)item { return self; }
@end

#pragma mark -

@implementation FOutlineViewArrayElement
- (id)init {
	if(self = [super init]) {
		_children = [[NSMutableArray alloc] init];
	}
	return self;
}

- (void)dealloc {
	[_children release];
	[super dealloc];
}

- (id<FOutlineViewElement>)item { return self; }

- (NSArray *)children { return _children; }
- (void)insertObject:(id)o inChildrenAtIndex:(unsigned)index {
	[_children insertObject:o atIndex:index];
}
- (void)removeObjectFromChildrenAtIndex:(unsigned)index {
	[_children removeObjectAtIndex:index];
}

- (void)addElement:(id)element {
	[self addElements:[NSArray arrayWithObject:element]];
}

- (void)addElements:(NSArray *)elements {
	[[self mutableArrayValueForKey:@"children"] addObjectsFromArray:elements];
}

- (void)removeElement:(id)element {
	[self removeElements:[NSArray arrayWithObject:element]];
}

- (void)removeElements:(NSArray *)elements {
	[[self mutableArrayValueForKey:@"children"] removeObjectsInArray:elements];
}

@end
	
#pragma mark -

@implementation FOutlineViewDataSource

- (id)initWithRoot:(id<FOutlineViewElement>)root {
	NSAssert(root,@"Root object cannot be nil.");
	if(self = [super init]) {
		_root = [root retain];
	}
	return self;
}

- (id)initWithRoot:(id<FOutlineViewElement>)root outlineView:(NSOutlineView *)outlineView {
	if(self = [self initWithRoot:root]) {
		[self installOnOutlineView:outlineView];
	}
	return self;
}

- (void)dealloc {
	[_root release];
	[super dealloc];
}

- (void)setRoot:(id<FOutlineViewElement>)root {
	[_root release];
	_root = [root retain];
}

- (id<FOutlineViewElement>)root { return _root; }

- (void)installOnOutlineView:(NSOutlineView *)outlineView {
	[outlineView setDataSource:[self retain]];
}

- (void)uninstallFromOutlineView:(NSOutlineView *)outlineView {
	if([outlineView dataSource]==self) {
		[outlineView setDataSource:nil];
		[self release];
	}
}		

- (void)setTableColumn:(NSTableColumn *)tableColumn performsSelector:(SEL)selector {
	[tableColumn setIdentifier:[SelectorWrapper wrapSelector:selector]];
}

- (void)setOutlineView:(NSOutlineView *)outlineView tableColumnNumber:(unsigned)num performsSelector:(SEL)selector {
	[self setTableColumn:(NSTableColumn *)[[outlineView tableColumns] objectAtIndex:num] performsSelector:selector];
}

#pragma mark OutlineView Data Source Protocol
//
// Data Source Protocol
//

- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item {
	//return the object representing the row to display
	NSAssert(item==nil || [item conformsToProtocol:@protocol(FOutlineViewElement)],@"Items in the FOutlineViewDataSource must all conform to the FOutlineViewElement protocol.");
	id<FOutlineViewElement> fove = item?item:_root;
	return [[[fove item] children] objectAtIndex:index];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
	//return true if we can expand this item
	NSAssert(item==nil || [item conformsToProtocol:@protocol(FOutlineViewElement)],@"Items in the FOutlineViewDataSource must all conform to the FOutlineViewElement protocol.");
	id<FOutlineViewElement> fove = item;
	BOOL b = [[fove item] expandable];
	return b;
}

- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
	NSAssert(item==nil || [item conformsToProtocol:@protocol(FOutlineViewElement)],@"Items in the FOutlineViewDataSource must all conform to the FOutlineViewElement protocol.");
	id<FOutlineViewElement> fove = item?item:_root;
	return [[[fove item] children] count];
}

- (id)outlineView:(NSOutlineView *)outlineView 
	objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
	//return the object representing the column given the row item
	NSAssert(item==nil || [item conformsToProtocol:@protocol(FOutlineViewElement)],@"Items in the FOutlineViewDataSource must all conform to the FOutlineViewElement protocol.");
	NSAssert([[tableColumn identifier] isKindOfClass:[SelectorWrapper class]],@"The FOutlineViewDataSource has not been set to perform a selector for at least one column.");

	id<FOutlineViewElement> fove = item;
	return [[fove item] performSelector:[(FSelectorWrapper *)[tableColumn identifier] selector]];
}

@end
